﻿using System;
using Super_Management_Mayhem.GameRoot;
using Transformable_Engine_v2.Engine.Animation.Trajectory;
using Transformable_Engine_v2.Engine.GameObjects.Containers;
using Transformable_Engine_v2.Engine.Helper;
using Transformable_Engine_v2.Engine.Time;
using Transformable_Engine_v2.Engine.Transformable_Math.Geometry;

namespace Super_Management_Mayhem.Screens.Playing.Players.Manager
{
    public partial class Manager
    {
        private const int CAMERA_OFFSET = 64;
        private const int CAMERA_MOVE_TIME = 500;

        private Container _camera;
        private ITrajectory _cameraEasing;
        private TE_Vector2 _cameraEndPosition;
        private TE_Vector2 _cameraStartPosition;
        private Timer _cameraTimer;

        public TE_Vector2 CameraPosition
        {
            get
            {
                return _camera.Position;
            }
        }

        private void CalculateCameraPosition(bool hasWarped,
                                             TE_Vector2 _forcedPosition)
        {
            var newPosition = new TE_Vector2(_player.Position);

            if(_forcedPosition == null)
            {
                switch (_latestDirection)
                {
                    case Direction.Down:
                        newPosition.AddOffset(0, CAMERA_OFFSET);
                        break;
                    case Direction.Up:
                        newPosition.AddOffset(0, -CAMERA_OFFSET);
                        break;
                    case Direction.Left:
                        newPosition.AddOffset(-CAMERA_OFFSET, 0);
                        break;
                    case Direction.Right:
                        newPosition.AddOffset(CAMERA_OFFSET, 0);
                        break;
                }
                newPosition = ClampCamera(newPosition);
            }
            else
            {
                newPosition = ClampCamera(_forcedPosition);
            }

            if (hasWarped)
            {
                SetCameraPosition(newPosition);
            }
            else
            {
                _cameraStartPosition = _camera.Position;
                _cameraEndPosition = newPosition;
                _cameraTimer.Reset();
            }
        }

        private TE_Vector2 ClampCamera(TE_Vector2 newPosition)
        {
            TE_Vector2 mapSize = Playscreen.Map.Size;
            TE_Vector2 viewSize = SuperManagementMayhem.HalfViewSize;

            return new TE_Vector2(newPosition.X.Clamp(viewSize.X, mapSize.X - viewSize.X - 32), newPosition.Y.Clamp(viewSize.Y, mapSize.Y - viewSize.Y + 32));
        }

        private void EndCameraMovement()
        {
            _camera.Position = _cameraEndPosition;
        }

        private void InitializeCamera(TE_Vector2 previousCameraPosition)
        {
            _camera = new Container();
            _cameraTimer = new Timer(CAMERA_MOVE_TIME, false, EndCameraMovement);
            _camera.AddTimers(_cameraTimer);
            _cameraEasing = new QuadraticEasing(BaseTrajectory.Easing.EaseOut);

            AddChildren(_camera);

            if(previousCameraPosition == null)
                SetCameraPosition(_player.Position);
            else
            {
                SetCameraPosition(previousCameraPosition);
                //When changing class, don't make the camera skip
                CalculateCameraPosition(false, _player.Position);
            }
        }

        private void SetCameraPosition(TE_Vector2 newPosition)
        {
            _camera.Position = ClampCamera(newPosition);

            _cameraTimer.Stop();
        }

        private void UpdateCamera(TimeSpan gameTime)
        {
            if (_cameraTimer.IsStarted)
            {
                _camera.Position = (_cameraEndPosition - _cameraStartPosition) *
                                   _cameraEasing.GetPercentageProgression(_cameraTimer.PercentageElapsed) +
                                   _cameraStartPosition;
            }
        }
    }
}
